package util;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

public class B2CConverter {

    private static final Map<String, Charset> encodingToCharsetCache = new HashMap<String, Charset>();

    public static final Charset ISO_8859_1;
    public static final Charset UTF_8;

    static {
        for (Charset charset: Charset.availableCharsets().values()) {
            encodingToCharsetCache.put(
                    charset.name().toLowerCase(Locale.US), charset);
            for (String alias : charset.aliases()) {
                encodingToCharsetCache.put(
                        alias.toLowerCase(Locale.US), charset);
            }
        }
        Charset iso88591 = null;
        Charset utf8 = null;
        try {
            iso88591 = getCharset("ISO-8859-1");
            utf8 = getCharset("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        ISO_8859_1 = iso88591;
        UTF_8 = utf8;
    }

    public static Charset getCharset(String enc)
            throws UnsupportedEncodingException{
        String lowerCaseEnc = enc.toLowerCase(Locale.US);
        Charset charset = encodingToCharsetCache.get(lowerCaseEnc);
        if (charset == null) {
            throw new UnsupportedEncodingException("b2cConverter.unknownEncoding");
        }
        return charset;
    }

//    private IntermediateInputStream iis;
//    private ReadConvertor conv;
//    private CharsetDecoder decoder;
//    private String encoding;
//
//    public B2CConverter(String encoding) throws IOException {
//        this.encoding=encoding;
//        reset();
//    }
//
//    public  void recycle() {
//        conv.recycle();
//        decoder.reset();
//    }
//
//    static final int BUFFER_SIZE=8192;
//    char result[]=new char[BUFFER_SIZE];
//
//    /**
//     * Convert a buffer of bytes into a chars.
//     *
//     * @param bb    Input byte buffer
//     * @param cb    Output char buffer
//     * @param limit Number of bytes to convert
//     * @throws IOException
//     */
//    public void convert( ByteChunk bb, CharChunk cb, int limit)
//        throws IOException
//    {
//        iis.setByteChunk( bb );
//        try {
//            // read from the reader
//            int bbLengthBeforeRead = 0;
//            while( limit > 0 ) {
//                int size = limit < BUFFER_SIZE ? limit : BUFFER_SIZE;
//                bbLengthBeforeRead = bb.getLength();
//                int cnt=conv.read( result, 0, size );
//                if( cnt <= 0 ) {
//                    // End of stream ! - we may be in a bad state
//                    if(log.isDebugEnabled()) {
//                        log.debug("B2CConverter: EOF");
//                    }
//                    return;
//                }
//                if(log.isDebugEnabled()) {
//                    log.debug("B2CConverter: Converted: " +
//                            new String(result, 0, cnt));
//                }
//                cb.append( result, 0, cnt );
//                limit = limit - (bbLengthBeforeRead - bb.getLength());
//            }
//        } catch( IOException ex) {
//            if(log.isDebugEnabled()) {
//                log.debug("B2CConverter: Reseting the converter " + ex.toString());
//            }
//            reset();
//            throw ex;
//        }
//    }
//
//
//    public void reset() throws IOException {
//        // Re-create the reader and iis
//        iis = new IntermediateInputStream();
//        decoder = getCharset(encoding).newDecoder();
//        conv = new ReadConvertor(iis, decoder);
//    }
//
//}
//
//// -------------------- Private implementation --------------------
//
//
//
///**
// *
// */
//final class ReadConvertor extends InputStreamReader {
//
//    /** Create a converter.
//     */
//    public ReadConvertor(IntermediateInputStream in, CharsetDecoder decoder) {
//        super(in, decoder);
//    }
//
//    /** Overridden - will do nothing but reset internal state.
//     */
//    @Override
//    public  final void close() throws IOException {
//        // NOTHING
//        // Calling super.close() would reset out and cb.
//    }
//
//    @Override
//    public  final int read(char cbuf[], int off, int len)
//        throws IOException
//    {
//        // will do the conversion and call write on the output stream
//        return super.read( cbuf, off, len );
//    }
//
//    /** Reset the buffer
//     */
//    public  final void recycle() {
//        try {
//            // Must clear super's buffer.
//            while (ready()) {
//                // InputStreamReader#skip(long) will allocate buffer to skip.
//                read();
//            }
//        } catch(IOException ioe){
//        }
//    }
//}
//
//
///** Special output stream where close() is overridden, so super.close()
//    is never called.
//
//    This allows recycling. It can also be disabled, so callbacks will
//    not be called if recycling the converter and if data was not flushed.
//*/
//final class IntermediateInputStream extends InputStream {
//    ByteChunk bc = null;
//
//    public IntermediateInputStream() {
//    }
//
//    @Override
//    public  final void close() throws IOException {
//        // shouldn't be called - we filter it out in writer
//        throw new IOException("close() called - shouldn't happen ");
//    }
//
//    @Override
//    public  final  int read(byte cbuf[], int off, int len) throws IOException {
//        return bc.substract(cbuf, off, len);
//    }
//
//    @Override
//    public  final int read() throws IOException {
//        return bc.substract();
//    }
//
//    // -------------------- Internal methods --------------------
//
//
//    void setByteChunk( ByteChunk mb ) {
//        bc = mb;
//    }

}
